#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from lxml import etree


class ParseXml:
    def __init__(self, file_path):
        self.element_tree = etree.parse(file_path)
        self.root = self.element_tree.getroot()

    @staticmethod
    def get_comment_text(comment):
        return comment.text

    @staticmethod
    def get_element_tag(element):
        return element.tag

    @staticmethod
    def get_element_attributes(element):
        attr = element.items()
        xpath = ParseXml.get_element_xpath(element)
        attr_dic = {'>>XPath': xpath}
        _attr_dic = dict(map(lambda t: (t[0], str(t[1])), attr))
        attr_dic.update(_attr_dic)
        return attr_dic

    @staticmethod
    def get_element_type(element):
        if isinstance(element, etree._Comment):
            return 'Commentary'
        elif isinstance(element, etree._Element):
            return 'Element'
        else:
            return None

    @staticmethod
    def get_element_xpath(element):
        _xpath = ''

        def rec(_xpath_list, _element):
            if _element is not None:
                _xpath_list.append(_element.tag)
                pel = _element.getparent()
                rec(_xpath_list, pel)
            else:
                _xpath_list.reverse()
                nonlocal _xpath
                _xpath = '>>' + '/'.join(_xpath_list)
            return _xpath
        return rec([], element)

    @staticmethod
    def get_element_list(root_element):
        if len(list(root_element)) > 0:

            def rec(_etree_list, _root_element):
                for element in _root_element:
                    _etree_list.append(element)
                    if len(list(element)) > 0:
                        rec(_etree_list, element)
                return _etree_list

            return rec([], root_element)
        else:
            return []

    @staticmethod
    def divide_element_list(element_list):
        typ = ParseXml.get_element_type(element_list[0])
        sub_list = [element_list[0]]
        new_list = [sub_list]
        for element in element_list[1:]:
            _typ = ParseXml.get_element_type(element)
            if _typ == typ:
                sub_list.append(element)
            else:
                typ = _typ
                sub_list = [element]
                new_list.append(sub_list)
        return new_list

    def make_xml_string(self):
        xml_string = etree.tostring(self.element_tree, encoding="UTF-8", pretty_print=True).decode("utf-8")
        return '<?xml version="1.0" encoding="UTF-8"?>\n' + xml_string

    @staticmethod
    def refactor_element(element_list):
        new_element_list = list()
        for idx, element in enumerate(element_list):
            typ = ParseXml.get_element_type(element)
            if typ == 'Commentary':
                cmt = ParseXml.get_comment_text(element)
                new_element_list.append({'Commentary': cmt})
            elif typ == 'Element':
                attr = ParseXml.get_element_attributes(element)
                # 过滤掉有空字符串的属性值
                attr = dict(filter(lambda t: t[1] != '', attr.items()))
                new_element_list.append({'Element': attr})
        return new_element_list


if __name__ == '__main__':
    path_01 = r'E:\Workspace\Projects\GDTools\DiffXml\activity_01.xml'
    xml_01 = ParseXml(path_01)
    root_01 = xml_01.root
    element_list_01 = xml_01.get_element_list(root_01)
    element_list_01 = xml_01.refactor_element(element_list_01)

    path_02 = r'E:\Workspace\Projects\GDTools\DiffXml\activity_02.xml'
    xml_02 = ParseXml(path_02)
    root_02 = xml_02.root
    element_list_02 = xml_02.get_element_list(root_02)
    element_list_02 = xml_02.refactor_element(element_list_02)

    for idx, element in enumerate(element_list_01):
        if element not in element_list_02:
            print('list1拥有差异元素{0}，位置{1}'.format(element, idx + 1))
    for idx, element in enumerate(element_list_02):
        if element not in element_list_01:
            print('list2拥有差异元素{0}，位置{1}'.format(element, idx + 1))